﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Windows.Forms;
using System.Diagnostics;
using System.Globalization;

namespace EPMAuditing.EventHandlers.RegisterEvents
{
    public partial class formMain : Form
    {
        private List<EnrolledEvent> _enrolledEvents;
        private List<EnrolledEvent> _enrolledEventsInitial;
        private List<ProjectServerEvent> _availableEvents;

        private LoginFormsWS.LoginForms loginForms = new LoginFormsWS.LoginForms();
        private LoginWindowsWS.LoginWindows loginWin = new LoginWindowsWS.LoginWindows();
        private EventsWS.Events events = new EventsWS.Events();

        private const string LOGIN_FORMS_URL = "_vti_bin/PSI/loginForms.asmx";
        private const string LOGIN_WIN_URL = "_vti_bin/PSI/loginWindows.asmx";
        private const string EVENTS_URL = "_vti_bin/PSI/events.asmx";
        private bool _loggedIn = false;

        private AppState _appState = AppState.Ready;

        private string _projectServerUrl;
        private string _assemblyName;
        private string _assemblyVersion;
        private string _assemblyCulture;
        private string _assemblyPublicKey;
        private bool _useDefaultCredentials = true;
        private bool _isWindowsAuth = true;
        private bool _simulateProjectServer = false;

        private enum AppState
        {
            Starting,
            ReadingEvents,
            FillingTreeViews,
            UpdatingEnrolledEvents,
            Ready,
            Error
        }

        #region Inialization

        public formMain()
        {
            InitializeComponent();
            ApplicationState = AppState.Starting;
            InitializeData();
        }

        private void InitializeData()
        {
            _projectServerUrl = Properties.Settings.Default.ProjectServerURL;
            _assemblyName = Properties.Settings.Default.AssemblyName;
            _assemblyVersion = Properties.Settings.Default.AssemblyVersion;
            _assemblyCulture = Properties.Settings.Default.AssemblyCulture;
            _assemblyPublicKey = Properties.Settings.Default.AssemblyPublicKey;
            _useDefaultCredentials = Properties.Settings.Default.UseDefaultCredentials;
            _simulateProjectServer = Properties.Settings.Default.SimulateProjectServer;
        }

        private void SaveData()
        {
            Properties.Settings.Default.ProjectServerURL = _projectServerUrl;
            Properties.Settings.Default.AssemblyName = _assemblyName;
            Properties.Settings.Default.AssemblyVersion = _assemblyVersion;
            Properties.Settings.Default.AssemblyCulture = _assemblyCulture;
            Properties.Settings.Default.AssemblyPublicKey = _assemblyPublicKey;
            Properties.Settings.Default.UseDefaultCredentials = _useDefaultCredentials;
            Properties.Settings.Default.SimulateProjectServer = _simulateProjectServer;
            Properties.Settings.Default.Save();
        }

        private string FQAssembly
        {
            get
            {
                // EPMAuditing.EventHandlers.LookupTableEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1e3db2b86a6e0210
                return string.Format(CultureInfo.InvariantCulture, "{0}, Version={1}, Culture={2}, PublicKeyToken={3}", _assemblyName, _assemblyVersion, _assemblyCulture, _assemblyPublicKey);
            }
        }

        //private string FQAssembly(string className)
        //{
        //    // EPMAuditing.EventHandlers.LookupTableEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1e3db2b86a6e0210
        //    return string.Format("{0}.{1}, Version={2}, Culture={3}, PublicKeyToken={4}", _assemblyName, className, _assemblyVersion, _assemblyCulture, _assemblyPublicKey);
        //}

        private void formMain_Load(object sender, EventArgs e)
        {
            EnableButtons(false);
            ApplicationState = AppState.Ready;
        }

        #endregion

        #region Working with Project Server

        private bool ReadEventLists()
        {
            ApplicationState = AppState.ReadingEvents;
            if (ReadEnrolledEvents())
            {
                if (ReadAvailableEvents())
                {
                    ApplicationState = AppState.Ready;
                    return true;
                }
            }
            ApplicationState = AppState.Error;
            return false;
        }

        private bool ReadAvailableEvents()
        {
            if (_simulateProjectServer)
                return SimulateReadAvailableEvents();

            EventsWS.EventsDataSet dsAvailableEvents;

            if (ConnectToProjectServer())
            {
                _availableEvents = new List<ProjectServerEvent>();

                try
                {
                    dsAvailableEvents = events.ReadEventsList();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "An exception occurred reading available events, exception: {0}", ex.Message),
                        "EPM Auditing", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }

                foreach (EventsWS.EventsDataSet.EventRow er in dsAvailableEvents.Event)
                {
                    _availableEvents.Add(new ProjectServerEvent(er.EventName, er.SourceName, er.EventId));
                }
            }
            else
            {
                MessageBox.Show("Cannot connect to Project Server, check for correct URL", "EPM Auditing",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            return true;
        }

        private bool ReadEnrolledEvents()
        {
            if (_simulateProjectServer)
                return SimulateReadEnrolledEvents();

            _enrolledEventsInitial = new List<EnrolledEvent>();
            EventsWS.EventHandlersDataSet dsEventHandlers;

            if (ConnectToProjectServer())
            {
                int i = 0;
                try
                {
                    dsEventHandlers = events.ReadEventHandlerAssociations();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "An exception occurred reading enrolled events, exception: {0}", ex.Message),
                        "EPM Auditing", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
                foreach (EventsWS.EventHandlersDataSet.EventHandlersRow ehr in dsEventHandlers.EventHandlers)
                {
                    i++;
                    // Check if the event is part of the EPM Auditing solution
                    if (ehr.AssemblyName.StartsWith(_assemblyName, StringComparison.OrdinalIgnoreCase))
                    {
                        _enrolledEventsInitial.Add(new EnrolledEvent(ehr.AssemblyName, BaseClassName(ehr.ClassName), ehr.Description,
                            ehr.EventHandlerUid, ehr.EventId, ehr.Name, ehr.Order, true, true));
                    }
                }
            }
            else
            {
                MessageBox.Show("Cannot connect to Project Server, check for correct URL", "EPM Auditing",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            return true;
        }

        private static string BaseClassName(string fullClassName)
        {
            int startpos =  fullClassName.LastIndexOf(".", StringComparison.OrdinalIgnoreCase) + 1;
            int length = fullClassName.LastIndexOf("Events", StringComparison.OrdinalIgnoreCase) - startpos;
            return fullClassName.Substring(startpos, length);            
        }

        private bool UpdateProjectServerEvents(List<EnrolledEvent> lee)
        {
            bool success = true;
            ApplicationState = AppState.UpdatingEnrolledEvents;

            if (_simulateProjectServer)
            {
                return SimulateUpdateProjectServerEvents(lee);
            }

            Dictionary<string, List<EnrolledEvent>> enrolledEventDictionary = new Dictionary<string,List<EnrolledEvent>>();

            if (lee.Count > 0)
            {
                foreach (EnrolledEvent ee in lee)
                {
                    if (!enrolledEventDictionary.ContainsKey(ee.ClassName))
                    {
                        enrolledEventDictionary.Add(ee.ClassName, new List<EnrolledEvent>());
                    }
                    enrolledEventDictionary[ee.ClassName].Add(ee);
                }

                foreach (KeyValuePair<string, List<EnrolledEvent>> kvp in enrolledEventDictionary)
                {
                    success = success && UpdateProjectServerEventClass(kvp.Value);
                }
            }


            ApplicationState = AppState.Ready;
            return success;

        }


        private bool UpdateProjectServerEventClass(List<EnrolledEvent> lee)
        {

            bool success = false;
            EventsWS.EventHandlersDataSet enabledEventHandlers = new EventsWS.EventHandlersDataSet();
            List<Guid> disabledEventHandlers = new List<Guid>();
            //Debug.Listeners.Add(new TextWriterTraceListener(@"c:\temp\eventstoenroll.csv"));
            //Debug.AutoFlush = true;

            if (lee.Count > 0)
            {
                foreach (EnrolledEvent ee in lee)
                {
                    //Debug.WriteLine(string.Format("{0}, {1}", ee.EventName, ee.QualifiedName));
                    if (ee.IsEnabled == true)
                        enabledEventHandlers.EventHandlers.Rows.Add(ee.EventHandlersRow(enabledEventHandlers));
                    else
                        disabledEventHandlers.Add(ee.EventHandlerUid);
                }

                try
                {
                    if (enabledEventHandlers.EventHandlers.Rows.Count > 0)
                        events.CreateEventHandlerAssociations(enabledEventHandlers);

                    if (disabledEventHandlers.Count > 0)
                        events.DeleteEventHandlerAssociations(disabledEventHandlers.ToArray());

                    success = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "An exception occurred updating events, exception: {0}", ex.Message),
                        "EPM Auditing", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    ApplicationState = AppState.Error;
                    success = false;
                }

            }

            return success;

        }

        private bool ConnectToProjectServer()
        {
            if (_simulateProjectServer)
            {
                return SimulateConnectToProjectServer();
            }

            if (!_loggedIn)
            {
                // Build the URL.
                string sProjectServerURL = _projectServerUrl;
                CredentialsForm formCredentials = new CredentialsForm();

                if (!sProjectServerURL.EndsWith("/", StringComparison.OrdinalIgnoreCase))
                {
                    sProjectServerURL = sProjectServerURL + "/";
                }

                if (_useDefaultCredentials)
                {
                    loginWin.Credentials = CredentialCache.DefaultCredentials;
                    loginWin.Url = sProjectServerURL + LOGIN_WIN_URL;
                }
                else
                {
                    if (formCredentials.ShowDialog() == DialogResult.OK)
                    {
                        if (formCredentials.IsWindowsAuth)
                        {
                            _isWindowsAuth = true;
                            loginWin.Credentials = new NetworkCredential(formCredentials.UserName, formCredentials.Domain, formCredentials.Password);
                            loginWin.Url = sProjectServerURL + LOGIN_WIN_URL;
                        }
                        else
                        {
                            _isWindowsAuth = false;
                            loginForms.CookieContainer = new CookieContainer();
                            loginForms.Url = sProjectServerURL + LOGIN_FORMS_URL;
                        }
                        formCredentials.Close();
                    }
                    else
                    {
                        MessageBox.Show("You must enter credentials, or select use default credentials");
                        formCredentials.Close();
                        return false;
                    }
                }

                // Login to project server.
                try
                {
                    events.Url = sProjectServerURL + EVENTS_URL;
                    if (_isWindowsAuth)
                    {
                        _loggedIn = loginWin.Login();
                        events.Credentials = CredentialCache.DefaultCredentials;
                    }
                    else
                    {
                        _loggedIn = loginForms.Login(formCredentials.UserName, formCredentials.Password);
                        events.Credentials = loginForms.Credentials;
                        events.CookieContainer = loginForms.CookieContainer;
                    }


                    return _loggedIn;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "An Exception occurred {0} at {1}", ex.Message, ex.Source));
                    ApplicationState = AppState.Error;
                    return false;
                }
            }

            return true;
        }

        #endregion

        #region Simulate Working with Project Server

        private bool SimulateReadAvailableEvents()
        {
            string[] groups = { "a", "b", "c", "d" };
            int eventsInGroup = 5;
            int eventId = 0;

            _availableEvents = new List<ProjectServerEvent>();
            foreach (string group in groups)
            {
                for (int i = 0; i < eventsInGroup; i++)
                {
                    _availableEvents.Add(new ProjectServerEvent(string.Format(CultureInfo.InvariantCulture, "{0}{1}", group, i.ToString()), group, eventId++));
                }
            }
            return true;
        }

        private bool SimulateReadEnrolledEvents()
        {
            _enrolledEventsInitial = new List<EnrolledEvent>();
            _enrolledEventsInitial.Add(new EnrolledEvent("EPMAuditing.EventHandlers.LookupTableEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1e3db2b86a6e0210",
                "a", "Description of a3", Guid.NewGuid(), 3, "a3", 1, true, true));
            return true;
        }

        private bool SimulateUpdateProjectServerEvents(List<EnrolledEvent> lee)
        {
            ApplicationState = AppState.UpdatingEnrolledEvents;
            MessageBox.Show("Simulating Updating Project Server Events", "EPM Auditing",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
            ApplicationState = AppState.Ready;
            return true;

        }

        private bool SimulateConnectToProjectServer()
        {
            return true;
        }

        #endregion

        #region System Properties

        private AppState ApplicationState
        {
            set
            {
                _appState = value;
                switch (_appState)
                {
                    case AppState.Ready:
                        Cursor = Cursors.Default;
                        toolStripStatusLabel1.Text = "Ready";
                        break;
                    case AppState.Error:
                        Cursor = Cursors.Default;
                        toolStripStatusLabel1.Text = "Error";
                        break;
                    case AppState.ReadingEvents:
                        Cursor = Cursors.WaitCursor;
                        toolStripStatusLabel1.Text = "Reading Events";
                        break;
                    case AppState.FillingTreeViews:
                        Cursor = Cursors.WaitCursor;
                        toolStripStatusLabel1.Text = "Filling Tree Views";
                        break;
                    case AppState.Starting:
                        Cursor = Cursors.WaitCursor;
                        toolStripStatusLabel1.Text = "Starting";
                        break;
                    case AppState.UpdatingEnrolledEvents:
                        Cursor = Cursors.WaitCursor;
                        toolStripStatusLabel1.Text = "Updating Enrolled Events";
                        break;
                }
                Application.DoEvents();
            }
        }

        #endregion

        #region Buttons

        private void buttonAddAllToEnrolled_Click(object sender, EventArgs e)
        {
            if (treeViewAvailableEvents.Nodes.Count > 0)
            {
                if (DialogResult.Yes == MessageBox.Show("This will add all events to the enrolled list, are you sure you want to do this?",
                    "EPM Auditing Register", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1))
                {
                    CopyAllToEnrolledTreeView();
                    ClearAvailableTreeView();
                }
            }
        }

        private void buttonAddOneToEnrolled_Click(object sender, EventArgs e)
        {
            if (treeViewAvailableEvents.SelectedNode != null)
            {
                if (treeViewAvailableEvents.SelectedNode.Level == 0)
                {
                    // Root Node add group of items
                    CopyGroupToEnrolledTreeView(treeViewAvailableEvents.SelectedNode.Name);
                    RemoveGroupFromAvailableTreeView(treeViewAvailableEvents.SelectedNode.Name);
                }
                else
                {
                    // Add a single item
                    AddNodeToEnrolledTreeView(treeViewAvailableEvents.SelectedNode);
                    RemoveNodeFromAvailableTreeView(treeViewAvailableEvents.SelectedNode);
                }
            }
        }

        private void buttonRemoveOneFromEnrolled_Click(object sender, EventArgs e)
        {
            if (treeViewEnrolledEvents.SelectedNode != null)
            {
                string nodeName = treeViewEnrolledEvents.SelectedNode.Name;
                if (treeViewEnrolledEvents.SelectedNode.Level == 0)
                {
                    // Root Node add group of items
                    CopyGroupToAvailableTreeView(nodeName);
                    RemoveGroupFromEnrolledTreeView(nodeName);
                    DisableGroupEnrolledEvents(nodeName);
                }
                else
                {
                    // Add a single item
                    AddNodeToAvailableTreeView(treeViewEnrolledEvents.SelectedNode);
                    RemoveNodeFromEnrolledTreeView(treeViewEnrolledEvents.SelectedNode);
                    DisableEnrolledEvent(nodeName);
                }
            }
        }

        private void buttonRemoveAllFromEnrolled_Click(object sender, EventArgs e)
        {
            if (treeViewEnrolledEvents.Nodes.Count > 0)
            {
                if (DialogResult.Yes == MessageBox.Show("This will remove all events from the enrolled list, are you sure you want to do this?",
                    "EPM Auditing Register", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1))
                {
                    ClearEnrolledTreeView();
                    DisableAllEnrolledEvents();
                    FillAvailableTreeView();
                }
            }
        }


        private void buttonRevertToOriginal_Click(object sender, EventArgs e)
        {
            FillTreeViews();
        }

        private void buttonExpandAvailableEvents_Click(object sender, EventArgs e)
        {
            treeViewAvailableEvents.ExpandAll();
        }

        private void buttonExpandEnrolledEvents_Click(object sender, EventArgs e)
        {
            treeViewEnrolledEvents.ExpandAll();
        }

        private void buttonCollapseAvailableEvents_Click(object sender, EventArgs e)
        {
            treeViewAvailableEvents.CollapseAll();
        }

        private void buttonCollapseEnrolledEvents_Click(object sender, EventArgs e)
        {
            treeViewEnrolledEvents.CollapseAll();
        }

        private void EnableButtons(bool enable)
        {
            buttonExpandEnrolledEvents.Enabled = enable;
            buttonExpandAvailableEvents.Enabled = enable;
            buttonRevertToOriginal.Enabled = enable;
            buttonRemoveAllFromEnabled.Enabled = enable;
            buttonRemoveOneFromEnabled.Enabled = enable;
            buttonAddOneToEnabled.Enabled = enable;
            buttonAddAllToEnabled.Enabled = enable;
            buttonCollapseAvailableEvents.Enabled = enable;
            buttonCollapseEnrolledEvents.Enabled = enable;
        }

        #endregion

        #region Operate on TreeViews

        private void FillTreeViews()
        {
            ApplicationState = AppState.FillingTreeViews;
            FillEnrolledTreeView();
            FillAvailableTreeView();
            ApplicationState = AppState.Ready;

        }

        private void FillAvailableTreeView()
        {

            if (treeViewAvailableEvents.Nodes.Count > 0)
                treeViewAvailableEvents.Nodes.Clear();

            treeViewAvailableEvents.BeginUpdate();

            foreach (ProjectServerEvent pse in _availableEvents)
            {
                if (!EnrolledEventEnabled(pse.EventName))
                {
                    if (!treeViewAvailableEvents.Nodes.ContainsKey(pse.ClassName))
                        treeViewAvailableEvents.Nodes.Add(pse.ClassName, pse.ClassName);

                    treeViewAvailableEvents.Nodes[pse.ClassName].Nodes.Add(pse.EventName, pse.EventName);
                }
            }
            //treeViewAvailableEvents.Sort();
            treeViewAvailableEvents.EndUpdate();
        }

        private void FillEnrolledTreeView()
        {
            if (_enrolledEvents != null)
                _enrolledEvents.Clear();
            else
                _enrolledEvents = new List<EnrolledEvent>();


            foreach (EnrolledEvent ee in _enrolledEventsInitial)
            {
                _enrolledEvents.Add(ee.Copy());
            }

            treeViewEnrolledEvents.BeginUpdate();

            if (treeViewEnrolledEvents.Nodes.Count > 0)
                treeViewEnrolledEvents.Nodes.Clear();

            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.IsEnabled)
                {
                    if (!treeViewEnrolledEvents.Nodes.ContainsKey(es.ClassName))
                        treeViewEnrolledEvents.Nodes.Add(es.ClassName, es.ClassName);

                    treeViewEnrolledEvents.Nodes[es.ClassName].Nodes.Add(es.EventName, es.EventName);
                }
            }
            treeViewEnrolledEvents.Sort();
            treeViewEnrolledEvents.EndUpdate();
        }

        private void ClearAvailableTreeView()
        {
            treeViewAvailableEvents.Nodes.Clear();
        }

        private void CopyGroupToEnrolledTreeView(string ClassName)
        {
            treeViewEnrolledEvents.BeginUpdate();
            TreeNodeCollection nodes = treeViewAvailableEvents.Nodes[ClassName].Nodes;
            //MessageBox.Show(string.Format("CopyAllToEnabled Count {0}", nodes.Count.ToString()));
            foreach (TreeNode tn in nodes)
            {
                //MessageBox.Show(string.Format("CopyAllToEnabled {0}", n.Name));

                AddNodeToEnrolledTreeView(tn);
            }
            treeViewEnrolledEvents.EndUpdate();
        }

        private void RemoveGroupFromAvailableTreeView(string ClassName)
        {
            treeViewAvailableEvents.Nodes[ClassName].Nodes.Clear();
            treeViewAvailableEvents.Nodes[ClassName].Remove();
        }

        private void CopyAllToEnrolledTreeView()
        {
            treeViewEnrolledEvents.BeginUpdate();
            TreeNodeCollection nodes = treeViewAvailableEvents.Nodes;
            //MessageBox.Show(string.Format("CopyAllToEnabled Count {0}", nodes.Count.ToString()));
            foreach (TreeNode n in nodes)
            {
                //MessageBox.Show(string.Format("CopyAllToEnabled {0}", n.Name));

                CopyEnrolledTreeViewRecursive(n);
            }
            treeViewEnrolledEvents.EndUpdate();
        }


        private void CopyEnrolledTreeViewRecursive(TreeNode treeNode)
        {
            foreach (TreeNode tn in treeNode.Nodes)
            {
                //MessageBox.Show(string.Format("CopyRecursive {0}", tn.Name));
                AddNodeToEnrolledTreeView(tn);
                CopyEnrolledTreeViewRecursive(tn);
            }
        }


        private void AddNodeToEnrolledTreeView(TreeNode tn)
        {
            //Get event information
            ProjectServerEvent pse = GetAvailableEvent(tn.Name);
            //MessageBox.Show(string.Format("{0}", pse.QualifiedName));

            // Add to Enrolled box
            if (!treeViewEnrolledEvents.Nodes.ContainsKey(pse.ClassName))
                treeViewEnrolledEvents.Nodes.Add(pse.ClassName, pse.ClassName);

            treeViewEnrolledEvents.Nodes[pse.ClassName].Nodes.Add(pse.EventName, pse.EventName);

            // Add to internal list
            EnableEnrolledEvent(pse);

        }

        private void RemoveNodeFromAvailableTreeView(TreeNode tn)
        {
            treeViewAvailableEvents.Nodes.Remove(tn);
        }

        private void ClearEnrolledTreeView()
        {
            treeViewEnrolledEvents.Nodes.Clear();
        }

        private void CopyGroupToAvailableTreeView(string ClassName)
        {
            treeViewAvailableEvents.BeginUpdate();
            TreeNodeCollection nodes = treeViewEnrolledEvents.Nodes[ClassName].Nodes;
            foreach (TreeNode tn in nodes)
            {
                AddNodeToAvailableTreeView(tn);
            }
            treeViewAvailableEvents.EndUpdate();
        }

        private void RemoveGroupFromEnrolledTreeView(string ClassName)
        {
            treeViewEnrolledEvents.Nodes[ClassName].Nodes.Clear();
            treeViewEnrolledEvents.Nodes[ClassName].Remove();
        }

        private void AddNodeToAvailableTreeView(TreeNode tn)
        {
            //Get event information
            ProjectServerEvent pse = GetAvailableEvent(tn.Name);
            //MessageBox.Show(string.Format("{0}", pse.QualifiedName));

            // Add to available box
            if (!treeViewAvailableEvents.Nodes.ContainsKey(pse.ClassName))
                treeViewAvailableEvents.Nodes.Add(pse.ClassName, pse.ClassName);

            treeViewAvailableEvents.Nodes[pse.ClassName].Nodes.Add(pse.EventName, pse.EventName);
        }

        private void RemoveNodeFromEnrolledTreeView(TreeNode tn)
        {
            treeViewEnrolledEvents.Nodes.Remove(tn);
        }


        #endregion

        #region List Methods

        private ProjectServerEvent GetAvailableEvent(string EventName)
        {
            foreach (ProjectServerEvent pse in _availableEvents)
            {
                if (pse.EventName == EventName)
                    return pse;
            }
            return null;
        }

        private bool AvailableEventExists(string EventName)
        {
            foreach (ProjectServerEvent pse in _availableEvents)
            {
                if (pse.EventName == EventName)
                    return true;
            }
            return false;
        }

        private EnrolledEvent GetEnrolledEvent(string EventName)
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.EventName == EventName)
                    return es;
            }
            return null;
        }

        private bool EnrolledEventExists(string EventName)
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.EventName == EventName)
                    return true;
            }
            return false;
        }

        private bool EnrolledEventEnabled(string EventName)
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.EventName == EventName)
                {
                    if (es.IsEnabled)
                        return true;
                    else
                        return false;
                }
            }
            return false;
        }

        private void DisableAllEnrolledEvents()
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                es.IsEnabled = false;
            }
        }

        private void DisableEnrolledEvent(string EventName)
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.EventName == EventName)
                {
                    es.IsEnabled = false;
                    return;
                }
            }
        }

        private void EnableEnrolledEvent(ProjectServerEvent pse)
        {
            // Add to internal list
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.EventName == pse.EventName)
                {
                    es.IsEnabled = true;
                    return;
                }
            }
            _enrolledEvents.Add(new EnrolledEvent(FQAssembly, pse, false, true));
        }

        private void DisableGroupEnrolledEvents(string EventName)
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                if (es.EventName.StartsWith(EventName, StringComparison.OrdinalIgnoreCase))
                {
                    es.IsEnabled = false;
                }
            }
        }

        private List<EnrolledEvent> GetChangedEnrolledEvents()
        {
            List<EnrolledEvent> lee = new List<EnrolledEvent>();

            if (_enrolledEvents != null)
            {
                foreach (EnrolledEvent es in _enrolledEvents)
                {
                    if (es.IsEnabledInitial != es.IsEnabled)
                    {
                        lee.Add(es);
                    }
                }
            }
            return lee;
        }

        private void ResetChangedEnrolledEvents()
        {
            foreach (EnrolledEvent es in _enrolledEvents)
            {
                es.ResetInitialEnabled();
            }

            if (_enrolledEventsInitial != null)
                _enrolledEventsInitial.Clear();
            else
                _enrolledEventsInitial = new List<EnrolledEvent>();

            foreach (EnrolledEvent ee in _enrolledEvents)
            {
                _enrolledEventsInitial.Add(ee.Copy());
            }
        }

        private bool IsEnrolledEventsDirty()
        {
            if (_enrolledEvents != null)
            {
                foreach (EnrolledEvent es in _enrolledEvents)
                {
                    if (es.IsEnabledInitial != es.IsEnabled)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        #endregion

        #region Tree View Events

        private void treeViewAvailableEvents_DoubleClick(object sender, EventArgs e)
        {
            if (treeViewAvailableEvents.SelectedNode != null)
            {
                if (treeViewAvailableEvents.SelectedNode.Level == 0)
                {
                    // Root Node add group of items
                    CopyGroupToEnrolledTreeView(treeViewAvailableEvents.SelectedNode.Name);
                    RemoveGroupFromAvailableTreeView(treeViewAvailableEvents.SelectedNode.Name);
                }
                else
                {
                    // Add a single item
                    AddNodeToEnrolledTreeView(treeViewAvailableEvents.SelectedNode);
                    RemoveNodeFromAvailableTreeView(treeViewAvailableEvents.SelectedNode);
                }
            }

        }

        private void treeViewEnrolledEvents_DoubleClick(object sender, EventArgs e)
        {
            if (treeViewEnrolledEvents.SelectedNode != null)
            {
                string nodeName = treeViewEnrolledEvents.SelectedNode.Name;
                if (treeViewEnrolledEvents.SelectedNode.Level == 0)
                {
                    // Root Node add group of items
                    CopyGroupToAvailableTreeView(nodeName);
                    RemoveGroupFromEnrolledTreeView(nodeName);
                    DisableGroupEnrolledEvents(nodeName);
                }
                else
                {
                    // Add a single item
                    AddNodeToAvailableTreeView(treeViewEnrolledEvents.SelectedNode);
                    RemoveNodeFromEnrolledTreeView(treeViewEnrolledEvents.SelectedNode);
                    DisableEnrolledEvent(nodeName);
                }
            }

        }

        private void treeViewEnrolledEvents_DragDrop(object sender, DragEventArgs e)
        {
            // item dropped on Enrolled Events
            TreeNode passedNode = (System.Windows.Forms.TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
            if (passedNode.Level == 0)
            {
                // Root Node add group of items
                CopyGroupToEnrolledTreeView(passedNode.Name);
                RemoveGroupFromAvailableTreeView(passedNode.Name);
            }
            else
            {
                // Add a single item
                AddNodeToEnrolledTreeView(passedNode);
                RemoveNodeFromAvailableTreeView(passedNode);
            }
        }

        private void treeViewAvailableEvents_DragDrop(object sender, DragEventArgs e)
        {
            // item dropped on Available Events

            TreeNode passedNode = (System.Windows.Forms.TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");

            string nodeName = passedNode.Name;
            if (passedNode.Level == 0)
            {
                // Root Node add group of items
                CopyGroupToAvailableTreeView(nodeName);
                RemoveGroupFromEnrolledTreeView(nodeName);
                DisableGroupEnrolledEvents(nodeName);
            }
            else
            {
                // Add a single item
                AddNodeToAvailableTreeView(passedNode);
                RemoveNodeFromEnrolledTreeView(passedNode);
                DisableEnrolledEvent(nodeName);
            }
        }

        private void treeViewEvents_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void treeViewEvents_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DoDragDrop(e.Item, DragDropEffects.Move);
        }

        #endregion

        #region ToolStrip Menu

        private void toolStripButtonReadEventList_Click(object sender, EventArgs e)
        {
            Application.DoEvents();
            if (ReadEventLists())
            {
                toolStripStatusLabel2.Text = _projectServerUrl;
                toolStripButtonUpdateRegistration.Enabled = true;
                FillTreeViews();
                EnableButtons(true);
            }
            else
            {
                toolStripButtonUpdateRegistration.Enabled = true;
                toolStripStatusLabel2.Text = "Unconnected";
            }
        }

        private void toolStripButtonUpdateRegistration_Click(object sender, EventArgs e)
        {
            List<EnrolledEvent> lee = GetChangedEnrolledEvents();

            if (lee.Count > 0)
            {
                // Confirm Changes
                UpdatePSConfirm formUpdatePSConfirm = new UpdatePSConfirm();
                formUpdatePSConfirm.SetEnrolledEvents(lee);
                if (formUpdatePSConfirm.ShowDialog() == DialogResult.OK)
                {
                    // Change Project Server Events
                    if (UpdateProjectServerEvents(lee))
                    {
                        ResetChangedEnrolledEvents();
                    }
                   
                }
                formUpdatePSConfirm.Close();
            }
            else
            {
                MessageBox.Show("There were no changes, skipped updating Project Server events", "EPM Auditing",
                    MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
            }


        }

        private void toolStripButtonSettings_Click(object sender, EventArgs e)
        {
            FormUpdateConfiguration formUpdateConfig = new FormUpdateConfiguration(_projectServerUrl, _assemblyName, _assemblyVersion, _assemblyCulture,
                                    _assemblyPublicKey, _useDefaultCredentials);
            if (formUpdateConfig.ShowDialog() == DialogResult.OK)
            {
                _projectServerUrl = formUpdateConfig.ProjectServerUrl;
                _assemblyName = formUpdateConfig.AssemblyName;
                _assemblyVersion = formUpdateConfig.AssemblyVersion;
                _assemblyCulture = formUpdateConfig.AssemblyCulture;
                _assemblyPublicKey = formUpdateConfig.AssemblyPublicKey;
                _useDefaultCredentials = formUpdateConfig.UseDefaultCredentials;

                if (formUpdateConfig.Dirty)
                    SaveData();
            }
            formUpdateConfig.Close();

        }

        private void toolStripButtonExit_Click(object sender, EventArgs e)
        {
            formMain.ActiveForm.Close();
        }

        #endregion

        #region Menu Items

        private void readEventListsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }


        private void toolStripMenuItemUpdateProjectServer_Click(object sender, EventArgs e)
        {
        }

        private void toolStripMenuItemUpdateConfiguration_Click(object sender, EventArgs e)
        {

        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }


        #endregion

        private void formMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (IsEnrolledEventsDirty())
            {
                DialogResult dr = MessageBox.Show("Changes you've made have not been saved, would you like to save them now?",
                    "EPM Auditing", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                switch (dr)
                {
                    case DialogResult.Yes:
                        List<EnrolledEvent> lee = GetChangedEnrolledEvents();
                        UpdatePSConfirm formUpdatePSConfirm = new UpdatePSConfirm();
                        formUpdatePSConfirm.SetEnrolledEvents(lee);
                        if (formUpdatePSConfirm.ShowDialog() == DialogResult.OK)
                        {
                            if (!UpdateProjectServerEvents(lee))
                                e.Cancel = true;
                        }
                        else
                            e.Cancel = true;
                        break;
                    case DialogResult.Cancel:
                        e.Cancel = true;
                        break;
                    case DialogResult.No:
                        break;
                }
            }

        }



    }
}
